import json
from datetime import datetime
from time import mktime
from typing import Any
from wsgiref.handlers import format_date_time
import hmac
import hashlib
import base64
from urllib.parse import urlencode
from urllib.parse import urlparse
import websockets
from rasa_sdk.executor import CollectingDispatcher
from .llm_api import LLMAPI


class SparkAPI(LLMAPI):
    def __init__(self):
        super().__init__()
        self.spark_url = "wss://spark-api.xf-yun.com/v3.1/chat"
        self.APPID = "47f62fbf"
        self.APIKey = "f57cf11b1af1407fe1fed5a4c7357014"
        self.APISecret = "NGQ0OTFlM2FjYTA5OTdiNTVhMTVjYWI1"
        self.host = urlparse(self.spark_url).netloc
        self.path = urlparse(self.spark_url).path
        self.domain = "general" + "v3"
        self.system_name = "assistant"

    def create_spark_url(self) -> str:
        cur_time = datetime.now()
        date = format_date_time(mktime(cur_time.timetuple()))
        signature_origin = "host: " + self.host + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + self.path + " HTTP/1.1"

        signature_sha = hmac.new(
            self.APISecret.encode('utf-8'),
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()

        signature = base64.b64encode(signature_sha).decode(encoding='utf-8')

        authorization_origin = (f"api_key=\"{self.APIKey}\""
                                f", algorithm=\"hmac-sha256\""
                                f", headers=\"host date request-line\""
                                f", signature=\"{signature}\"")

        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')

        v = {
            "authorization": authorization,
            "date": date,
            "host": self.host
        }
        url = self.spark_url + '?' + urlencode(v)

        return url

    # context所有字符应当不超过spark的限制，默认8192长度
    def create_spark_request_json(self, uid, context):
        json_data = {
            "header": {
                "app_id": self.APPID,
                "uid": uid
            },
            "parameter": {
                "chat": {
                    "domain": self.domain
                }
            },
            "payload": {
                "message": {
                    "text": context
                }
            }
        }
        return json_data

    async def send_message_to_spark(self, json_data: str, dispatcher: CollectingDispatcher) -> str:

        # with open("json_data.json", "w", encoding="utf-8") as file:
        #    file.write(json.dumps(json.loads(json_data),ensure_ascii=False,indent=4))

        url = self.create_spark_url()

        async with (websockets.connect(url) as ws):
            await ws.send(json_data)
            response = ""

            async for data in ws:
                json_data = json.loads(data)

                if json_data["header"]["code"] != 0:
                    await ws.close()
                    dispatcher.utter_message("\n不好意思，我暂时无法继续回答你这个问题。")
                    break

                choices = json_data["payload"]["choices"]
                status = choices["status"]
                content = choices["text"][0]["content"]

                dispatcher.utter_message(content)

                if status == 2:
                    await ws.close()
                    break

            return response

    async def ask(self, events: list[dict[str, Any]], dispatcher: CollectingDispatcher) -> str:
        base_require = "现在你是蒙古族英雄史诗《江格尔》中的主人公\"江格尔\"，你需要以\"江格尔\"的第一人称和口吻来与我进行对话。"
        base_answer = "好的，我现在将使用江格尔的第一人称和口吻来进行对话。"
        base_context = [
            {"role": "user", "content": base_require},
            {"role": "assistant", "content": base_answer}
        ]
        context = self.generate_context(events, base_context)
        json_data = self.create_spark_request_json("", context)
        response = await self.send_message_to_spark(json.dumps(json_data, ensure_ascii=False), dispatcher)

        return response

    async def optimize_response(self,
                                events: list[dict[str, Any]],
                                source_response: str,
                                dispatcher: CollectingDispatcher) -> str:
        temp_events = [events[len(events)-1]]
        base_require = "现在你是蒙古族英雄史诗《江格尔》中的主人公\"江格尔\"，你需要以\"江格尔\"的第一人称和口吻来说我发给你的句子。"
        base_answer = "好的，我会尽力以江格尔的第一人称和口吻来说你发给我的句子。"
        base_context = [
            {"role": "user", "content": base_require},
            {"role": "assistant", "content": base_answer}
        ]
        context = self.generate_context(temp_events, base_context)
        context.pop()
        context.append({"role": "user", "content": source_response})
        json_data = self.create_spark_request_json("", context)
        response = await self.send_message_to_spark(json.dumps(json_data), dispatcher)
        # print(f"response:{response}")
        return response
